%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tabvar.h"

typedef struct types{
     char * chaine;
     int entier;
     double reel;
}types;


#define YYSTYPE types

#define DOUBLE "double"
#define POINT "pointeur"
%}

%token REEL IDENTIFICATEUR TYPE RETURN ADRESSE

%%

bloc_extern     : '{' list_decl bloc_intern RETURN expr ';' '}'  {printf("\nValeur finale retournee : %f\n\n", $5.reel);}
                ;

bloc_intern     : '{' bloc_intern '}' bloc_intern
                | list_aff
                |
                ;


list_decl       : declaration list_decl
                | declaration
                ;

list_aff        : affectation list_aff
                | affectation
                ;

declaration     : type IDENTIFICATEUR ';'                         {tabvar_declarer($2.chaine, $1.chaine, 0); }
                ;

type            : TYPE                                            {$$.chaine = $1.chaine; }
                | TYPE '*'                                        {$$.chaine = chaine_dup(POINT);} 
                ;


affectation     :  IDENTIFICATEUR '=' expr ';'                    {if(strcmp(tabvar_recuperer_type($1.chaine), POINT) == 0)
                                                                       {
                                                                        fprintf(stderr, "\nLigne %d : "
                                                                                        "Attribution d'une adresse erronnee "
               							                        "a un pointeur.\n", get_nb_ligne());
                                                                        exit(EXIT_FAILURE);
               			                                       }
                                                                    else tabvar_affecter($1.chaine, $3.reel);} 
                |  IDENTIFICATEUR '=' ADRESSE ';'                 {tabvar_affecter_adresse($1.chaine, $3.chaine);
                                                                   if(!strcmp(tabvar_recuperer_type($1.chaine), POINT) == 0)
                                                                     {
                                                                       fprintf(stderr, "\nLigne %d : Attribution d'une adresse a "
							                               "une variable non pointeur.\n", get_nb_ligne());
						                       exit(EXIT_FAILURE);
                                                                      }
                                                                  }
                | '(' '*' IDENTIFICATEUR ')' '=' expr ';'         {if(strcmp(tabvar_recuperer_type($3.chaine), POINT) == 0)
                                        		             tabvar_affecter(tabvar_recuperer_adresse($3.chaine), $6.reel);
		                                                   else
                                                                    {
                                                                     fprintf(stderr, "\nLigne %d : Attribution impossible, "
                                                                                     "la variable \"%s\" n'est pas de type "
								                     "pointeur\n", get_nb_ligne(),$3.chaine);
							              exit(EXIT_FAILURE);
                                                                     }
                                                                   }
                ;


expr            : terme '+' expr                                   { $$.reel = $1.reel+$3.reel; }
                | terme                                            { $$.reel = $1.reel; }
                | terme '-' expr                                   { $$.reel = $1.reel-$3.reel; }
                ;

terme           : facteur '*' terme                                { $$.reel = $1.reel*$3.reel; }
                | facteur                                          { $$.reel = $1.reel; }
                | facteur '/' terme                                { if ($3.reel == 0) printf("\nErreur: division par zero\n");}
                ;

facteur         : '(' expr ')'                                     { $$.reel = $2.reel;}
                | REEL                                             { $$.reel = $1.reel; }
                | IDENTIFICATEUR                                   { $$.reel = tabvar_recuperer($1.chaine); }
                | '(' '*' IDENTIFICATEUR ')'                       { $$.reel = tabvar_recuperer(tabvar_recuperer_adresse($3.chaine));}
                ;


%%
#include "lex.yy.c"

int main(int argc, char ** argv){
  yyparse();
  tabvar_afficher();

  return EXIT_SUCCESS;
}

int yyerror(char * s){
  printf("Erreur syntaxique: %s\n", s);

  return 1;
}
